package com.codedancer.campus.client.interceptor;


import cn.hutool.core.util.ObjectUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.codedancer.campus.common.anno.PassToken;
import com.codedancer.campus.common.exception.BusinessException;
import com.codedancer.campus.common.utils.IpUtils;
import com.codedancer.campus.mapper.SchoolMapper;
import com.codedancer.campus.mapper.UserMapper;
import com.codedancer.campus.mapper.UserSchoolMapper;
import com.codedancer.campus.po.School;
import com.codedancer.campus.po.User;
import com.codedancer.campus.po.UserSchool;
import java.lang.reflect.Method;
import javax.security.auth.message.AuthException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * ClassName AuthInterceptor Description 用户认证拦截器
 **/
@Component
@Slf4j
public class AuthInterceptor implements HandlerInterceptor {


    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserSchoolMapper userSchoolMapper;
    @Autowired
    private SchoolMapper schoolMapper;

    /**
     * 登录验证
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
        Object handler)
        throws Exception {
        String token = request.getHeader("AUTH_TOKEN");
        if (ObjectUtil.isEmpty(token)) {
            token = request.getParameter("AUTH_TOKEN");
        }
        if (!(handler instanceof HandlerMethod)) {
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
        HandlerMethod handlerMethod = (HandlerMethod) handler;
        Method method = handlerMethod.getMethod();
        //检查是否有passtoken注释，有则跳过认证
        if (method.isAnnotationPresent(PassToken.class)) {
            PassToken passToken = method.getAnnotation(PassToken.class);
            if (passToken.required()) {
                return HandlerInterceptor.super.preHandle(request, response, handler);
            }
        } else {
            // 执行认证
            if (token == null) {
                log.error("登录token为空");
                throw new AuthException("登录失效，请重新登录");
            }
            // 获取 token 中的  uuid
            String uuid;
            try {
                uuid = JWT.decode(token).getAudience().get(0);
            } catch (JWTDecodeException j) {
                log.error("uuid不存在，token：{}", token);
                throw new AuthException("登录失效，请重新登录");
            }
            User user = userMapper.selectById(uuid);
            if (ObjectUtils.isEmpty(user)) {
                log.error("用户不存在，token：{}", token);
                throw new AuthException("登录失效，请重新登录");
            }
            // 判断用户是否被禁用
            if (user.getDisabled()) {
                throw new AuthException("账号已被禁用，请联系管理员");
            }
            // 是否设置了基本信息
            if (user.getIsSetBasicMessage()) {
                // 已设置
                // 判断学校是否存在或者被禁用
                UserSchool userSchool = userSchoolMapper
                    .selectOneByColumn("user_uuid", uuid);
                if (ObjectUtil.isEmpty(userSchool)) {
                    throw new AuthException("你还未绑定学校");
                }
                School school = schoolMapper.selectById(userSchool.getSchoolUuid());
                if (ObjectUtil.isEmpty(school)) {
                    throw new AuthException("你绑定的学校不存在，请联系管理员");
                }
                if (school.getDisabled()) {
                    throw new AuthException("你绑定的学校已被禁用，请联系管理员");
                }
            }
            // 验证 token
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
            try {
                jwtVerifier.verify(token);
            } catch (JWTVerificationException e) {
                log.error("token校验失败，token：{}", token);
                throw new AuthException("登录失效，请重新登录");
            }
            return HandlerInterceptor.super.preHandle(request, response, handler);
        }
        return HandlerInterceptor.super.preHandle(request, response, handler);
    }
}
